﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using ICSharpCode.AvalonEdit.Document;
using System.ComponentModel;
using System.Windows.Threading;

namespace SQLBuilderWPF.View_Models
{
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public MainWindowViewModel()
        {
            this.mapinfoexpression = new MapinfoSQLExpression();
            this.mapinfoexpression.Select = new SelectExpression();
            this.mapinfoexpression.From = new FromExpression();
            this.mapinfoexpression.Where = new WhereExpression();

            this.mapinfoexpression.From.TableList = "Hello World, Test";

            this.finalSQLtextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(finalSQLtextdoc_Changed);
            this.selecttextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(selecttextdoc_Changed);
            this.wheretextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(wheretextdoc_Changed);
        }

        public List<FunctionViewModel> Functions
        {
            get
            {
                List<FunctionViewModel> functions = new List<FunctionViewModel>();
                var function1 = new FunctionViewModel();
                var function2 = new FunctionViewModel();
                var function3 = new FunctionViewModel();
                var function4 = new FunctionViewModel();
                var function5 = new FunctionViewModel();
                function1.FunctionName = "ObjectInfo";
                function1.FunctionHelp = "Returns Pen, Brush, or other values describing a graphical object.";
                function2.FunctionName = "ObjectLen";
                function2.FunctionHelp = "Returns Pen, Brush, or other values describing a graphical object.";
                function3.FunctionName = "CentroidX";
                function3.FunctionHelp = "Returns the x-coordinate of the centroid of an object.";
                function4.FunctionName = "ObjectInfo4";
                function4.FunctionHelp = "Gets infomation about a object";
                functions.Add(function1);
                functions.Add(function2);
                functions.Add(function3);
                functions.Add(function4);
                return functions;
            }
        }

        public MapinfoSQLExpression mapinfoexpression { get; set; }

        public string FromString
        {
            get
            {
                return this.mapinfoexpression.From.TableList;
            }
            set
            {
                this.mapinfoexpression.From.TableList = value;
                this.FirePropertyChanged("FinalSQLString");
            }
        }

        TextDocument wheretextdoc = new TextDocument();
        public TextDocument WhereString
        {
            get
            {
                wheretextdoc.Text = this.mapinfoexpression.Where.Conditions;
                return wheretextdoc;
            }
        }


        TextDocument selecttextdoc = new TextDocument();
        public TextDocument SelectString
        {
            get
            {
                selecttextdoc.Text = this.mapinfoexpression.Select.Projections;
                return selecttextdoc;
            }
        }

        TextDocument finalSQLtextdoc = new TextDocument();
        public TextDocument FinalSQLString
        {
            get
            {
                finalSQLtextdoc.Text = this.mapinfoexpression.ToExpression();
                return finalSQLtextdoc;
            }
        }

        void wheretextdoc_Changed(object sender, DocumentChangeEventArgs e)
        {
            this.mapinfoexpression.Where.Conditions = this.wheretextdoc.Text;
            this.finalSQLtextdoc.Changed -= new EventHandler<DocumentChangeEventArgs>(finalSQLtextdoc_Changed);
            this.FirePropertyChanged("FinalSQLString");
            this.finalSQLtextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(finalSQLtextdoc_Changed);
        }

        void selecttextdoc_Changed(object sender, DocumentChangeEventArgs e)
        {
            this.mapinfoexpression.Select.Projections = this.selecttextdoc.Text;
            this.finalSQLtextdoc.Changed -= new EventHandler<DocumentChangeEventArgs>(finalSQLtextdoc_Changed);
            this.FirePropertyChanged("FinalSQLString");
            this.finalSQLtextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(finalSQLtextdoc_Changed);
        }

        void finalSQLtextdoc_Changed(object sender, DocumentChangeEventArgs e)
        {
            //TODO Parse the entered string correctly.
            this.mapinfoexpression.ParseString(this.finalSQLtextdoc.Text);
            
            // Remove handlers to stop loop updates.
            this.selecttextdoc.Changed -= new EventHandler<DocumentChangeEventArgs>(selecttextdoc_Changed);
            this.wheretextdoc.Changed -= new EventHandler<DocumentChangeEventArgs>(wheretextdoc_Changed);

            this.FirePropertyChanged("SelectString");
            this.FirePropertyChanged("WhereString");

            // Add the handlers back to let the updates happen again.
            this.selecttextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(selecttextdoc_Changed);
            this.wheretextdoc.Changed += new EventHandler<DocumentChangeEventArgs>(wheretextdoc_Changed);

            //Because the FromString is just a normal textbox we don't have to worry about unwiring the events.
            this.FirePropertyChanged("FromString");
        }


        private void FirePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }
    }
}
